home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / pine3.07 / pico / basic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-18  |  14.7 KB  |  513 lines

  1. /*
  2.  * Program:    ANSI terminal functions
  3.  *
  4.  * Modifier:    Michael Seibel
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: mikes@cac.washington.edu
  11.  *
  12.  * Date:    19 Jan 1991
  13.  * Last Edited:    6 Jan 1992
  14.  *
  15.  * Copyright 1991 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35. /*
  36.  * The routines in this file move the cursor around on the screen. They
  37.  * compute a new value for the cursor, then adjust ".". The display code
  38.  * always updates the cursor location, so only moves between lines, or
  39.  * functions that adjust the top line in the window and invalidate the
  40.  * framing, are hard.
  41.  */
  42. #include        <stdio.h>
  43. #include    "estruct.h"
  44. #include        "edef.h"
  45. #include        "pico.h"
  46.  
  47. /*
  48.  * Move the cursor to the
  49.  * beginning of the current line.
  50.  * Trivial.
  51.  */
  52. gotobol(f, n)
  53. {
  54.         curwp->w_doto  = 0;
  55.         return (TRUE);
  56. }
  57.  
  58. /*
  59.  * Move the cursor backwards by "n" characters. If "n" is less than zero call
  60.  * "forwchar" to actually do the move. Otherwise compute the new cursor
  61.  * location. Error if you try and move out of the buffer. Set the flag if the
  62.  * line pointer for dot changes.
  63.  */
  64. backchar(f, n)
  65. register int    n;
  66. {
  67.         register LINE   *lp;
  68.         register int    status;
  69.  
  70.         if (n < 0)
  71.                 return (forwchar(f, -n));
  72.         while (n--) {
  73.                 if (curwp->w_doto == 0) {
  74.             if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  75.             if(Pmaster){
  76.                 /*
  77.                  * go up into editing the mail header if on 
  78.                  * the top line and the user hits the left arrow!!!
  79.                  *
  80.                  * if the editor returns anything except -1, the 
  81.                  * user requested something special, so let 
  82.                  * pico know...
  83.                  */
  84.                 if((status = HeaderEditor(2, 1)) != -1){
  85.                 return(META|status);
  86.                 }
  87.                 else
  88.                   return (FALSE);
  89.             }
  90.             else
  91.               return (FALSE);
  92.             curwp->w_dotp  = lp;
  93.             curwp->w_doto  = llength(lp);
  94.             curwp->w_flag |= WFMOVE;
  95.                 } else
  96.             curwp->w_doto--;
  97.         }
  98.         return (TRUE);
  99. }
  100.  
  101. /*
  102.  * Move the cursor to the end of the current line. Trivial. No errors.
  103.  */
  104. gotoeol(f, n)
  105. {
  106.         curwp->w_doto  = llength(curwp->w_dotp);
  107.         return (TRUE);
  108. }
  109.  
  110. /*
  111.  * Move the cursor forwwards by "n" characters. If "n" is less than zero call
  112.  * "backchar" to actually do the move. Otherwise compute the new cursor
  113.  * location, and move ".". Error if you try and move off the end of the
  114.  * buffer. Set the flag if the line pointer for dot changes.
  115.  */
  116. forwchar(f, n)
  117. register int    n;
  118. {
  119.         if (n < 0)
  120.                 return (backchar(f, -n));
  121.         while (n--) {
  122.                 if (curwp->w_doto == llength(curwp->w_dotp)) {
  123.                         if (curwp->w_dotp == curbp->b_linep)
  124.                                 return (FALSE);
  125.                         curwp->w_dotp  = lforw(curwp->w_dotp);
  126.                         curwp->w_doto  = 0;
  127.                         curwp->w_flag |= WFMOVE;
  128.                 } else
  129.                         curwp->w_doto++;
  130.         }
  131.         return (TRUE);
  132. }
  133.  
  134. gotoline(f, n)        /* move to a particular line.
  135.                argument (n) must be a positive integer for
  136.                this to actually do anything        */
  137.  
  138. {
  139.     if (n < 1)        /* if a bogus argument...then leave */
  140.         return(FALSE);
  141.  
  142.     /* first, we go to the start of the buffer */
  143.         curwp->w_dotp  = lforw(curbp->b_linep);
  144.         curwp->w_doto  = 0;
  145.     return(forwline(f, n-1));
  146. }
  147.  
  148. /*
  149.  * Goto the beginning of the buffer. Massive adjustment of dot. This is
  150.  * considered to be hard motion; it really isn't if the original value of dot
  151.  * is the same as the new value of dot. Normally bound to "M-<".
  152.  */
  153. gotobob(f, n)
  154. {
  155.         curwp->w_dotp  = lforw(curbp->b_linep);
  156.         curwp->w_doto  = 0;
  157.         curwp->w_flag |= WFHARD;
  158.         return (TRUE);
  159. }
  160.  
  161. /*
  162.  * Move to the end of the buffer. Dot is always put at the end of the file
  163.  * (ZJ). The standard screen code does most of the hard parts of update.
  164.  * Bound to "M->".
  165.  */
  166. gotoeob(f, n)
  167. {
  168.         curwp->w_dotp  = curbp->b_linep;
  169.         curwp->w_doto  = 0;
  170.         curwp->w_flag |= WFHARD;
  171.         return (TRUE);
  172. }
  173.  
  174. /*
  175.  * Move forward by full lines. If the number of lines to move is less than
  176.  * zero, call the backward line function to actually do it. The last command
  177.  * controls how the goal column is set. Bound to "C-N". No errors are
  178.  * possible.
  179.  */
  180. forwline(f, n)
  181. {
  182.         register LINE   *dlp;
  183.  
  184.         if (n < 0)
  185.                 return (backline(f, -n));
  186.         if ((lastflag&CFCPCN) == 0)             /* Reset goal if last   */
  187.                 curgoal = getccol(FALSE);       /* not C-P or C-N       */
  188.         thisflag |= CFCPCN;
  189.         dlp = curwp->w_dotp;
  190.         while (n-- && dlp!=curbp->b_linep)
  191.                 dlp = lforw(dlp);
  192.         curwp->w_dotp  = dlp;
  193.         curwp->w_doto  = getgoal(dlp);
  194.         curwp->w_flag |= WFMOVE;
  195.         return (TRUE);
  196. }
  197.  
  198. /*
  199.  * This function is like "forwline", but goes backwards. The scheme is exactly
  200.  * the same. Check for arguments that are less than zero and call your
  201.  * alternate. Figure out the new line and call "movedot" to perform the
  202.  * motion. No errors are possible. Bound to "C-P".
  203.  */
  204. backline(f, n)
  205. {
  206.         register LINE   *dlp;
  207.         register int    status;
  208.  
  209.         if (n < 0)
  210.                 return (forwline(f, -n));
  211.  
  212.     if(Pmaster){
  213.         /*
  214.          * go up into editing the mail header if on the top line
  215.          * and the user hits the up arrow!!!
  216.          */
  217.         if (lback(curwp->w_dotp) == curbp->b_linep){
  218.         /*
  219.          * if the editor returns anything except -1 then the user
  220.          * has requested something special, so let pico know...
  221.          */
  222.         if((status = HeaderEditor(1, 1)) != -1){
  223.             return(META|status);
  224.         }
  225.         }
  226.     }
  227.  
  228.         if ((lastflag&CFCPCN) == 0)             /* Reset goal if the    */
  229.                 curgoal = getccol(FALSE);       /* last isn't C-P, C-N  */
  230.         thisflag |= CFCPCN;
  231.         dlp = curwp->w_dotp;
  232.         while (n-- && lback(dlp)!=curbp->b_linep)
  233.                 dlp = lback(dlp);
  234.         curwp->w_dotp  = dlp;
  235.         curwp->w_doto  = getgoal(dlp);
  236.         curwp->w_flag |= WFMOVE;
  237.         return (TRUE);
  238. }
  239.  
  240. gotobop(f, n)    /* go back to the begining of the current paragraph
  241.            here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  242.            combination to delimit the begining of a paragraph    */
  243.  
  244. int f, n;    /* default Flag & Numeric argument */
  245.  
  246. {
  247.     register int suc;    /* success of last backchar */
  248.  
  249.     if (n < 0)    /* the other way...*/
  250.         return(gotoeop(f, -n));
  251.  
  252.     while (n-- > 0) {    /* for each one asked for */
  253.  
  254.         /* first scan back until we are in a word */
  255.             while(!inword())
  256.           if(lback(curwp->w_dotp) == curbp->b_linep 
  257.              && curwp->w_doto == 0)
  258.             /* top line and nowhere else to go */
  259.             return(FALSE);
  260.           else if(backchar(FALSE, 1) == FALSE)
  261.             break;
  262.  
  263.         curwp->w_doto = 0;    /* and go to the B-O-Line */
  264.  
  265.         /* and scan back until we hit a <NL><NL> or <NL><TAB>
  266.            or a <NL><SPACE>                    */
  267.         while (lback(curwp->w_dotp) != curbp->b_linep)
  268.             if (llength(curwp->w_dotp) != 0 &&
  269.                 lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  270.                 lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  271.                 curwp->w_dotp = lback(curwp->w_dotp);
  272.             else
  273.                 break;
  274.  
  275.         /* and then forward until we are in a word */
  276.             while(!inword())
  277.           if(forwchar(FALSE,1) == FALSE)
  278.             break;
  279.     }
  280.     curwp->w_flag |= WFMOVE;    /* force screen update */
  281. }
  282.  
  283. gotoeop(f, n)    /* go forword to the end of the current paragraph
  284.            here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  285.            combination to delimit the begining of a paragraph    */
  286.  
  287. int f, n;    /* default Flag & Numeric argument */
  288.  
  289. {
  290.     register int suc;    /* success of last backchar */
  291.  
  292.     if (n < 0)    /* the other way...*/
  293.         return(gotobop(f, -n));
  294.  
  295.     while (n-- > 0) {    /* for each one asked for */
  296.  
  297.         /* first scan forward until we are in a word */
  298.             if(curwp->w_dotp != curbp->b_linep){
  299.             curwp->w_doto = 0;        /* go to the B-O-Line */
  300.             curwp->w_dotp = lforw(curwp->w_dotp);
  301.         }
  302.  
  303.         /* and scan forword until we hit a <NL><NL> or <NL><TAB>
  304.            or a <NL><SPACE>                    */
  305.         while (curwp->w_dotp != curbp->b_linep) {
  306.             if (llength(curwp->w_dotp) != 0 &&
  307.                 lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  308.                 lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  309.                 curwp->w_dotp = lforw(curwp->w_dotp);
  310.             else
  311.                 break;
  312.         }
  313.  
  314.         /* and then backward until we are in a word */
  315.         suc = TRUE;
  316.         while (suc && !inword()) {
  317.                 if(lback(curwp->w_dotp) == curbp->b_linep 
  318.                && curwp->w_doto == 0)
  319.               break;
  320.             suc = backchar(FALSE, 1);
  321.         }
  322.         curwp->w_doto = llength(curwp->w_dotp);    /* and to the EOL */
  323.     }
  324.     curwp->w_flag |= WFMOVE;    /* force screen update */
  325.     return(TRUE);
  326. }
  327.  
  328. /*
  329.  * This routine, given a pointer to a LINE, and the current cursor goal
  330.  * column, return the best choice for the offset. The offset is returned.
  331.  * Used by "C-N" and "C-P".
  332.  */
  333. getgoal(dlp)
  334. register LINE   *dlp;
  335. {
  336.         register int    c;
  337.         register int    col;
  338.         register int    newcol;
  339.         register int    dbo;
  340.  
  341.         col = 0;
  342.         dbo = 0;
  343.         while (dbo != llength(dlp)) {
  344.                 c = lgetc(dlp, dbo);
  345.                 newcol = col;
  346.                 if (c == '\t')
  347.                         newcol |= 0x07;
  348.                 else if (c<0x20 || c==0x7F)
  349.                         ++newcol;
  350.                 ++newcol;
  351.                 if (newcol > curgoal)
  352.                         break;
  353.                 col = newcol;
  354.                 ++dbo;
  355.         }
  356.         return (dbo);
  357. }
  358.  
  359. /*
  360.  * Scroll forward by a specified number of lines, or by a full page if no
  361.  * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  362.  * the overlap; this value is the default overlap value in ITS EMACS. Because
  363.  * this zaps the top line in the display window, we have to do a hard update.
  364.  */
  365. forwpage(f, n)
  366. register int    n;
  367. {
  368.         register LINE   *lp;
  369.         register int    nl;
  370.  
  371.         if (f == FALSE) {
  372.                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
  373.                 if (n <= 0)                     /* Forget the overlap   */
  374.                         n = 1;                  /* if tiny window.      */
  375.         } else if (n < 0)
  376.                 return (backpage(f, -n));
  377. #if     CVMVAS
  378.         else                                    /* Convert from pages   */
  379.                 n *= curwp->w_ntrows;           /* to lines.            */
  380. #endif
  381.         nl = n;
  382.         lp = curwp->w_linep;
  383.         while (n-- && lp!=curbp->b_linep)
  384.                 lp = lforw(lp);
  385.         curwp->w_dotp  = lp;
  386.         curwp->w_doto  = 0;
  387.         curwp->w_flag |= WFHARD;
  388.     if(lp == curbp->b_linep)
  389.       return(TRUE);
  390.     else
  391.       curwp->w_linep = lp;
  392.  
  393.         /*
  394.          * if the header is open, close it ...
  395.          */
  396.         if(Pmaster && ComposerTopLine != COMPOSER_TOP_LINE){
  397.         n -= ComposerTopLine - COMPOSER_TOP_LINE;
  398.             ToggleHeader(0);
  399.     }
  400.  
  401.     /*
  402.      * scroll down from the top the same number of lines we've moved 
  403.      * forward
  404.      */
  405.     if(optimize)
  406.       scrollup(curwp, -1, nl-n-1);
  407.  
  408.         return (TRUE);
  409. }
  410.  
  411. /*
  412.  * This command is like "forwpage", but it goes backwards. The "2", like
  413.  * above, is the overlap between the two windows. The value is from the ITS
  414.  * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  415.  * reason.
  416.  */
  417. backpage(f, n)
  418. register int    n;
  419. {
  420.         register LINE   *lp;
  421.         register int    nl;
  422.  
  423.         if (f == FALSE) {
  424.                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
  425.                 if (n <= 0)                     /* Don't blow up if the */
  426.                         n = 1;                  /* window is tiny.      */
  427.         } else if (n < 0)
  428.                 return (forwpage(f, -n));
  429. #if     CVMVAS
  430.         else                                    /* Convert from pages   */
  431.                 n *= curwp->w_ntrows;           /* to lines.            */
  432. #endif
  433.         nl = n;
  434.         lp = curwp->w_linep;
  435.         while (n-- && lback(lp)!=curbp->b_linep)
  436.                 lp = lback(lp);
  437.         curwp->w_linep = lp;
  438.         curwp->w_dotp  = lp;
  439.         curwp->w_doto  = 0;
  440.         curwp->w_flag |= WFHARD;
  441.  
  442.     /*
  443.      * scroll down from the top the same number of lines we've moved 
  444.      * forward
  445.      */
  446.  
  447.     /* 
  448.      * This isn't too cool, but it has to be this way so we can 
  449.      * gracefully scroll in the message header
  450.      */
  451.     if(Pmaster){
  452.         if((lback(lp)==curbp->b_linep) && (ComposerTopLine==COMPOSER_TOP_LINE))
  453.           n -= entry_line(LASTHDR, TRUE);
  454.         if(nl-n-1 < curwp->w_ntrows)
  455.           if(optimize)
  456.         scrolldown(curwp, -1, nl-n-1);
  457.     }
  458.     else
  459.       if(optimize)
  460.         scrolldown(curwp, -1, nl-n-1);
  461.  
  462.     if(Pmaster){
  463.         /*
  464.          * if we're at the top of the page, and the header is closed, 
  465.          * open it ...
  466.          */
  467.         if((lback(lp) == curbp->b_linep) 
  468.            && (ComposerTopLine == COMPOSER_TOP_LINE)){
  469.         ToggleHeader(1);
  470.         movecursor(ComposerTopLine, 0);
  471.         }
  472.     }
  473.  
  474.         return (TRUE);
  475. }
  476.  
  477. /*
  478.  * Set the mark in the current window to the value of "." in the window. No
  479.  * errors are possible. Bound to "M-.".
  480.  */
  481. setmark(f, n)
  482. {
  483.         curwp->w_markp = curwp->w_dotp;
  484.         curwp->w_marko = curwp->w_doto;
  485.         return (TRUE);
  486. }
  487.  
  488. /*
  489.  * Swap the values of "." and "mark" in the current window. This is pretty
  490.  * easy, bacause all of the hard work gets done by the standard routine
  491.  * that moves the mark about. The only possible error is "no mark". Bound to
  492.  * "C-X C-X".
  493.  */
  494. swapmark(f, n)
  495. {
  496.         register LINE   *odotp;
  497.         register int    odoto;
  498.  
  499.         if (curwp->w_markp == NULL) {
  500.         if(Pmaster == NULL)
  501.           mlwrite("No mark in this window");
  502.         return (FALSE);
  503.         }
  504.         odotp = curwp->w_dotp;
  505.         odoto = curwp->w_doto;
  506.         curwp->w_dotp  = curwp->w_markp;
  507.         curwp->w_doto  = curwp->w_marko;
  508.         curwp->w_markp = odotp;
  509.         curwp->w_marko = odoto;
  510.         curwp->w_flag |= WFMOVE;
  511.         return (TRUE);
  512. }
  513.